//泛型
// 指在定义函数、接口或类的时候，不预先指定具体的类型，而在使用的时候再指定具体类型的一种特性.
//----------------------------------泛型方法----------------------------------------------------------------------------
//定义泛型方法
function fu<T>(name: T): string {
    return '';
}

console.log(fu<string>('1'))

//泛型方法定义多个泛型
//const 函数名称 = <泛型列表>（参数列表）:返回值 => {方法体}
const a = <T, V>(name: T, value: V): [T, V] => {
    return [name, value]
}
//----------------------------------泛型接口----------------------------------------------------------------------------
//泛型接口
interface IPerson<T> {
    //泛型属性
    data: T[],
    //匿名函数赋值给变量
    add: (name: T) => void
    //返回一个泛型
    getPerson: (id: number) => T

}

class User {
    id: number | undefined
    name: string | undefined

    constructor(name: string | undefined) {
        this.name = name;
    }

}

//实现类 行为受泛型接口约束
class UserCRUD implements IPerson<User> {
    data: User[] = [];

    add(user: User) {
        //给user赋值id
        user = {...user, id: Date.now()}
        // @ts-ignore
        //完成添加逻辑
        this.data.pop(user);
        console.log('user保存成功', user.id);
    }

    getPerson(id: number): User {
        // @ts-ignore
        return this.data.find(time => {
            time.id === id
        });
    }
}

//实际使用
const user = new UserCRUD();
user.add(new User('张三'));
user.add(new User('李四'));
console.log(JSON.stringify(user.data));

//----------------------------------泛型类----------------------------------------------------------------------------
class GenericNumber<T> {
    zeroValue: T | undefined
    add: ((x: T, y: T) => T) | undefined
}

let aa = new GenericNumber<string>();
aa.zeroValue = '3';
aa.add = (x, y) => {
    return x + y;
}

//----------------------------------泛型约束------------------------------------------------------------------------------
// 指定泛型约束 这个泛型只能是string类型的子类
function fn2 <T extends string>(x: T): void {
    console.log(x.length)
}
class Fx {

}
//泛型约束也能直接继承自己创建的类
function fn3 <T extends Fx>(x: T): void {
    // console.log(x.length)
}
export {}
